/*
 * =====================================================================================
 *
 *       Filename:  check_skelbdb.c
 *
 *    Description:  unit test for tcskelbdb.c
 *
 *        Version:  1.0
 *        Created:  02/16/2010 22:06:06
 *       Revision:  $Reverision$
 *       Compiler:  gcc
 *
 *         Author:  Riceball LEE(riceball.lee@gmail.com) 
 *
 * =====================================================================================
 */

#include <stdlib.h>
#include <string.h>
#include <embUnit/embUnit.h>
#include <tcadb.h>
#include "../tcskelbdb.h"

static void _test_get(char *aKey, char *aExceptedValue);
static void _test_add(char *aKey, char *aValue);
static void _test_del(char *aKey);
static void _test_setindex(char *aFieldName, char *aFieldOpt);

static void test_add(void);

TCADB *CreateDB(void) {
  TCADB *vResult = tcadbnew();
  return vResult;
}

TCADB *GDB;

static void setup (void)
{
  GDB = CreateDB();
  TEST_ASSERT_MESSAGE(GDB != 0, "create ADB failed.");
  TEST_ASSERT_MESSAGE(tcADBSetSkelBDB(GDB), "set SkelBDB failed.");
  TEST_ASSERT_MESSAGE(tcadbopen(GDB, "./test.tcb"), "open ./test/tcb db failed");
#if defined DEBUG
  //fprintf(stderr, "%s\n", "CreateDB OK");
#endif
}

static void teardown (void)
{
  tcadbdel(GDB);
}

static void _test_get(char *aKey, char *aExceptedValue) {
  char *vValue = tcadbget2(GDB, aKey);  
  TEST_ASSERT_EQUAL_STRING(aExceptedValue, vValue);
  free(vValue);
}

static void _test_add(char *aKey, char *aValue) {
  TEST_ASSERT_MESSAGE(tcadbput2(GDB, aKey, aValue), "add the key/value failed.");
  _test_get(aKey, aValue);
}

static void _test_del(char *aKey) {
  TEST_ASSERT_MESSAGE(tcadbout2(GDB, aKey), "delete the key failed.");
}

static void _test_setindex(char *aFieldName, char *aFieldOpt) {
  TCLIST *vParams = tclistnew3(aFieldName, aFieldOpt);
  TCLIST *vResults;
  char vIdxName[MAXKEYLEN+1];
  
  vResults = tcadbmisc(GDB, "setindex", vParams);
  TEST_ASSERT_MESSAGE(vResults != NULL, "setindex return list is null error.");
  TEST_ASSERT_MESSAGE(tclistnum(vResults) == 0, "setindex return list count error.");
  tclistdel(vParams);
  tclistdel(vResults);
  strcpy(vIdxName, IDXCONFIGKEY);
  strcat(vIdxName, aFieldName);
  TEST_ASSERT_MESSAGE(tcadbvsiz2(GDB, vIdxName) >= 0, "setindex can not put the index configuration info correctly.");
  //TEST_ASSERT_MESSAGE(tcadbout2(GDB, vIdxName), "(setindex)delete the index config failed.");
}

static void test_clearDB(void) {
  TEST_ASSERT_MESSAGE(GDB != NULL, "the GDB is null");
  TEST_ASSERT_MESSAGE(tcadbvanish(GDB), "empty the DB failed.");
  TEST_ASSERT_MESSAGE(tcadbrnum(GDB) == 0, "empty the DB, but the DB record num is not 0");
  //TEST_ASSERT_MESSAGE(tcadbsize(GDB) == 0, "empty the DB, but the DB size is not 0");
}

static void test_delete(void) {
  test_add();
  TEST_ASSERT_MESSAGE(tcadbout2(GDB, "DfkdsjFH") == false, "delete the unexists key should be failed, but successful.");
  _test_del("myword1");
  TEST_ASSERT_MESSAGE(tcadbvsiz2(GDB, "myword1") == -1, "delete the myword1 key, but still can get the value.");

  char vIdxName[MAXKEYLEN+1];
  strcpy(vIdxName, IDXKEY);
  strcat(vIdxName, "key");
  strcat(vIdxName, "/");
  strcat(vIdxName, "\"hi\"");
  strcat(vIdxName, "/");
  strcat(vIdxName, "myword1");
  TEST_ASSERT_MESSAGE(tcadbvsiz2(GDB, vIdxName) == -1, "delete the myword1 key, but still can get the field 'key' index.");

  strcpy(vIdxName, IDXKEY);
  strcat(vIdxName, "goodkey");
  strcat(vIdxName, "/");
  strcat(vIdxName, "true");
  strcat(vIdxName, "/");
  strcat(vIdxName, "myword1");
  TEST_ASSERT_MESSAGE(tcadbvsiz2(GDB, vIdxName) == -1, "delete the myword1 key, but still can get the field 'goodkey' index.");

  strcpy(vIdxName, IDXKEY);
  strcat(vIdxName, "中文Key");
  strcat(vIdxName, "/");
  strcat(vIdxName, "\"世界你好\"");  
  strcat(vIdxName, "/");
  strcat(vIdxName, "myword1");
  TEST_ASSERT_MESSAGE(tcadbvsiz2(GDB, vIdxName) == -1, "delete the myword1 key, but still can get the field '中文Key' index.");

  _test_del("myword");
  TEST_ASSERT_MESSAGE(tcadbvsiz2(GDB, "myword") == -1, "delete the myword key, but still can get the value.");

  strcpy(vIdxName, IDXKEY);
  strcat(vIdxName, "key");
  strcat(vIdxName, "/");
  strcat(vIdxName, "\"hi\"");
  strcat(vIdxName, "/");
  strcat(vIdxName, "myword");
  TEST_ASSERT_MESSAGE(tcadbvsiz2(GDB, vIdxName) == -1, "delete the myword key, but still can get the field 'key' index.");
  strcpy(vIdxName, IDXKEY);
  strcat(vIdxName, "goodkey");
  strcat(vIdxName, "/");
  strcat(vIdxName, "true");
  strcat(vIdxName, "/");
  strcat(vIdxName, "myword");
  TEST_ASSERT_MESSAGE(tcadbvsiz2(GDB, vIdxName) == -1, "delete the myword key, but still can get the field 'goodkey' index.");

  strcpy(vIdxName, IDXKEY);
  strcat(vIdxName, "中文Key");
  strcat(vIdxName, "/");
  strcat(vIdxName, "\"世界你好\"");  
  strcat(vIdxName, "/");
  strcat(vIdxName, "myword");
  TEST_ASSERT_MESSAGE(tcadbvsiz2(GDB, vIdxName) == -1, "delete the myword key, but still can get the field '中文Key' index.");
}

static void test_add(void) {
  char vIdxName[MAXKEYLEN+1];

  TEST_ASSERT_MESSAGE(GDB != NULL, "the GDB is null");
  test_clearDB();
  //first add three index.
  _test_setindex("key", "0");
  _test_setindex("goodkey", "0");
  _test_setindex("中文Key", "0");
  _test_add("myword", "{\"so\":12,\"key\":\"hi\",\"goodkey\":true,\"中文Key\":\"世界你好\"}");
  TEST_ASSERT_MESSAGE(tcadbrnum(GDB) == 3+1+3, "add the key/value, but the record number is error.");
  strcpy(vIdxName, IDXKEY);
  strcat(vIdxName, "key");
  strcat(vIdxName, "/");
  strcat(vIdxName, "\"hi\"");
  strcat(vIdxName, "/");
  strcat(vIdxName, "myword");
  _test_get(vIdxName, "myword");
  
  strcpy(vIdxName, IDXKEY);
  strcat(vIdxName, "goodkey");
  strcat(vIdxName, "/");
  strcat(vIdxName, "true");
  strcat(vIdxName, "/");
  strcat(vIdxName, "myword");
  _test_get(vIdxName, "myword");

  strcpy(vIdxName, IDXKEY);
  strcat(vIdxName, "中文Key");
  strcat(vIdxName, "/");
  strcat(vIdxName, "\"世界你好\"");  
  strcat(vIdxName, "/");
  strcat(vIdxName, "myword");
  _test_get(vIdxName, "myword");

  //*[bug] The duplication index(FieldValue) not supported.
  _test_add("myword1", "{\"so\":122,\"key\":\"hi1\",\"goodkey\":true,\"中文Key\":\"世界你好\"}");
  TEST_ASSERT_MESSAGE(tcadbrnum(GDB) == 3+1+3+1+3, "add another the key/value, but the record number is error.");
  strcpy(vIdxName, IDXKEY);
  strcat(vIdxName, "key");
  strcat(vIdxName, "/");
  strcat(vIdxName, "\"hi1\"");
  strcat(vIdxName, "/");
  strcat(vIdxName, "myword1");
  _test_get(vIdxName, "myword1");
  
  strcpy(vIdxName, IDXKEY);
  strcat(vIdxName, "goodkey");
  strcat(vIdxName, "/");
  strcat(vIdxName, "true");
  strcat(vIdxName, "/");
  strcat(vIdxName, "myword1");
  _test_get(vIdxName, "myword1");

  strcpy(vIdxName, IDXKEY);
  strcat(vIdxName, "中文Key");
  strcat(vIdxName, "/");
  strcat(vIdxName, "\"世界你好\"");  
  strcat(vIdxName, "/");
  strcat(vIdxName, "myword1");
  _test_get(vIdxName, "myword1");
}

static void test_setindex(void)
{
  //fprintf(stderr, "begin %s\n", __FUNCTION__);
  
  /* unit test code */
  //char *vFieldKey = "key";
  //TCLIST *vResults;
  //TCLIST *vParams = tclistnew3(vFieldKey, "0");

  TEST_ASSERT_MESSAGE(GDB != NULL, "the GDB is null");

  test_clearDB();
  _test_setindex("key", "0");
  _test_setindex("goodkey", "0");
  _test_setindex("中文Key", "0");

  //TEST_ASSERT_MESSAGE(tcadbvanish(GDB), "empty the DB failed.");
  //TEST_ASSERT_MESSAGE(tcadbrnum(GDB) == 0, "empty the DB, but the DB record num is not 0");

  //fprintf(stderr,"%s\n","1");
  //vResults = tcadbmisc(GDB, "setindex", vParams);
  //fprintf(stderr, "res:%d\n", vResults);
  //TEST_ASSERT_MESSAGE(vResults != NULL, "setindex return list is null error.");
  //fprintf(stderr, "rescout:%d\n", tclistnum(vResults));
  //TEST_ASSERT_MESSAGE(tclistnum(vResults) == 0, "setindex return list count error.");
  
  //tclistdel(vResults);
  //char vIdxName[MAXKEYLEN+1];
  //strcpy(vIdxName, IDXCONFIGKEY);
  //strcat(vIdxName, vFieldKey);
  //TEST_ASSERT_MESSAGE(tcadbvsiz2(GDB, vIdxName) >= 0, "setindex can not put the index configuration info correctly.");
  //TEST_ASSERT_MESSAGE(tcadbout2(GDB, vIdxName), "(setindex)delete the index config failed.");
}

TestRef SkelBDB_tests( TestCaller *test )
{
	EMB_UNIT_TESTFIXTURES(fixtures) {
		new_TestFixture("test_clearDB",test_clearDB),
		new_TestFixture("test_Setindex",test_setindex),
    new_TestFixture("test_delete",test_delete),
		new_TestFixture("test_add",test_add)
	};
	EMB_UNIT_TESTCALLER(test,"SkelBDBTests",setup,teardown,fixtures);
  
	return (TestRef)test;
}
